home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / ghostscr / gsview07.zip / clip.c next >
C/C++ Source or Header  |  1993-05-10  |  38KB  |  1,422 lines

  1. /*
  2.  * clip.c --    Clipboard and EPS operations for GSVIEW.EXE, 
  3.  *              a graphical interface for MS-Windows Ghostscript
  4.  * Copyright (C) 1993  Russell Lang
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *   Author: Russell Lang
  21.  * Internet: rjl@monu1.cc.monash.edu.au
  22.  */
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <mmsystem.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <dir.h>
  35. #define NeedFunctionPrototypes 1
  36. #include "ps.h"
  37. #include "gsview.h"
  38.  
  39. #include <time.h>
  40.  
  41. #define COPY_BUF_SIZE 16384u
  42.  
  43. /* Write data to file - blocks > 64k permitted */
  44. long
  45. hwrite(HFILE hf, const void _huge *hpvBuffer, long cbBuffer)
  46. {
  47. DWORD count;
  48. long written, done;
  49. char _huge *hp;
  50.     if (is_win31)
  51.         return _hwrite(hf, hpvBuffer, cbBuffer);
  52.     done = 0;
  53.     hp = (char _huge *)hpvBuffer;
  54.     while (cbBuffer > 0) {
  55.         count = min( min(32768UL, cbBuffer), (DWORD)(65536UL-OFFSETOF(hp)) );
  56.         written = _lwrite(hf, hp, (UINT)count);
  57.         if (written == (long)HFILE_ERROR)
  58.         return (long)HFILE_ERROR;
  59.         done += written;
  60.         cbBuffer -= written;
  61.         hp += written;
  62.     }
  63.     return done;
  64. }
  65.  
  66. /* return number of bytes per line, rounded up to multiple of 4 bytes */
  67. LONG
  68. dib_bytewidth(LPBITMAPINFOHEADER pbmih)
  69. {
  70.  return (((pbmih->biWidth * pbmih->biBitCount + 31) & ~31) >> 3);
  71. }
  72.  
  73. /* return number of colors in color table */
  74. UINT
  75. dib_pal_colors(LPBITMAPINFOHEADER pbmih)
  76. {
  77. int bits_per_pixel = pbmih->biPlanes * pbmih->biBitCount;
  78.     if (bits_per_pixel != 24) {
  79.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER)) {
  80.         return 1<<bits_per_pixel;
  81.         }
  82.         else {
  83.         return (pbmih->biClrUsed) ? (UINT)(pbmih->biClrUsed) : 1<<bits_per_pixel;
  84.         }
  85.     }
  86.     return 0;
  87. }
  88.  
  89. /* copy a DIB from the clipboard to a file */
  90. void
  91. clip_to_file(void)
  92. {
  93. HGLOBAL hglobal;
  94. LPBITMAPINFOHEADER pbmih;
  95. BITMAPFILEHEADER bmfh;
  96. UINT palcolors;
  97. UINT palsize;
  98. DWORD bitmap_size;
  99. BYTE _huge *lpBits;
  100. static char output[MAXSTR];
  101. HFILE hfile;
  102.     if (!OpenClipboard(hwndimg)) {
  103.         play_sound(SOUND_ERROR);
  104.         return;
  105.     }
  106.     if (!IsClipboardFormatAvailable(CF_DIB)) {
  107.         CloseClipboard();
  108.         play_sound(SOUND_ERROR);
  109.         return;
  110.     }
  111.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  112.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  113.     palcolors = dib_pal_colors(pbmih);
  114.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  115.         palsize = palcolors * sizeof(RGBTRIPLE); 
  116.     else
  117.         palsize = palcolors * sizeof(RGBQUAD);
  118.     bitmap_size = (DWORD)pbmih->biHeight *  dib_bytewidth(pbmih);
  119.  
  120.     bmfh.bfType = ('M'<<8) | 'B';
  121.     bmfh.bfReserved1 = 0;
  122.     bmfh.bfReserved2 = 0;
  123.     bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + pbmih->biSize + palsize;
  124.     bmfh.bfSize = bmfh.bfOffBits + bitmap_size;
  125.  
  126.     if ( getfilename(output, SAVE, FILTER_BMP, NULL, IDS_TOPICEDIT)
  127.         && ((hfile = _lcreat(output, 0)) != HFILE_ERROR) ) {
  128.         hwrite(hfile, &bmfh, sizeof(BITMAPFILEHEADER));
  129.         hwrite(hfile, pbmih, pbmih->biSize + palsize);
  130.         lpBits =  ((BYTE _huge *)pbmih) + pbmih->biSize + palsize;
  131.         hwrite(hfile, lpBits, bitmap_size);
  132.         _lclose(hfile);
  133.     }
  134.     GlobalUnlock(hglobal);
  135.     CloseClipboard();
  136. }
  137.  
  138. /* convert bitmap (DIB or DDB) in clipboard to */
  139. /* CF_DIB, CF_BITMAP and CF_PALETTE */
  140. void
  141. clip_convert(void)
  142. {
  143.     if (!OpenClipboard(hwndimg)) {
  144.         play_sound(SOUND_ERROR);
  145.         return;
  146.     }
  147.     if (IsClipboardFormatAvailable(CF_DIB)) {
  148.         if (!IsClipboardFormatAvailable(CF_PALETTE))
  149.         clip_add_palette();
  150.         if (!IsClipboardFormatAvailable(CF_BITMAP))
  151.             clip_add_ddb();
  152.     }
  153.     else {
  154.         if (IsClipboardFormatAvailable(CF_BITMAP)) {
  155.         clip_add_dib();
  156.             if (!IsClipboardFormatAvailable(CF_PALETTE))
  157.             clip_add_palette();
  158.         }
  159.         else 
  160.         play_sound(SOUND_ERROR);
  161.     }
  162.     CloseClipboard();
  163. }
  164.  
  165. /* Read DIB from the clipboard, create PALETTE and add to clipboard */
  166. void
  167. clip_add_palette(void)
  168. {
  169. HGLOBAL hglobal;
  170. LPBITMAPINFOHEADER pbmih;
  171. UINT palcolors;
  172. UINT palsize;
  173. int i;
  174. LPLOGPALETTE logpalette;
  175. HPALETTE hpalette;
  176. RGBQUAD FAR *prgbquad;
  177. RGBTRIPLE FAR *prgbtriple;
  178.  
  179.     if (!IsClipboardFormatAvailable(CF_DIB)) {
  180.         play_sound(SOUND_ERROR);
  181.         return;
  182.     }
  183.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  184.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  185.     palcolors = dib_pal_colors(pbmih);
  186.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  187.         palsize = palcolors * sizeof(RGBTRIPLE); 
  188.     else
  189.         palsize = palcolors * sizeof(RGBQUAD);
  190.     hpalette = (HPALETTE)NULL;
  191.     if (palsize) {
  192.         /* create palette to match DIB */
  193.         logpalette = (LPLOGPALETTE) malloc( sizeof(LOGPALETTE) + 
  194.         palcolors * sizeof(PALETTEENTRY) );
  195.         if (logpalette == (LPLOGPALETTE)NULL) {
  196.         GlobalUnlock(hglobal);
  197.         play_sound(SOUND_ERROR);
  198.         return;
  199.         }
  200.         logpalette->palVersion = 0x300;
  201.         logpalette->palNumEntries = palcolors;
  202.         prgbquad = (RGBQUAD FAR *)(((BYTE _huge *)pbmih) + pbmih->biSize);
  203.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER)) {
  204.         /* OS2 format */
  205.             prgbtriple = (RGBTRIPLE FAR *)prgbquad;
  206.             for (i=0; i<palcolors; i++) {
  207.                 logpalette->palPalEntry[i].peFlags = 0;
  208.             logpalette->palPalEntry[i].peRed   = prgbtriple[i].rgbtRed;
  209.             logpalette->palPalEntry[i].peGreen = prgbtriple[i].rgbtGreen;
  210.             logpalette->palPalEntry[i].peBlue  = prgbtriple[i].rgbtBlue;
  211.             }
  212.         }
  213.         else {
  214.         /* Windows Format */
  215.             for (i=0; i<palcolors; i++) {
  216.                 logpalette->palPalEntry[i].peFlags = 0;
  217.             logpalette->palPalEntry[i].peRed   = prgbquad[i].rgbRed;
  218.             logpalette->palPalEntry[i].peGreen = prgbquad[i].rgbGreen;
  219.             logpalette->palPalEntry[i].peBlue  = prgbquad[i].rgbBlue;
  220.             }
  221.         }
  222.         hpalette = CreatePalette(logpalette);
  223.         free((void *)logpalette);
  224.         SetClipboardData(CF_PALETTE, hpalette);
  225.     }
  226.     GlobalUnlock(hglobal);
  227. }
  228.  
  229.  
  230. /* Read DIB from the clipboard, convert to DDB and add to clipboard */
  231. void
  232. clip_add_ddb(void)
  233. {
  234. HGLOBAL hglobal;
  235. LPBITMAPINFOHEADER pbmih;
  236. UINT palcolors;
  237. UINT palsize;
  238. HPALETTE hpalette;
  239. HDC hdc;
  240. HBITMAP hbitmap;
  241.  
  242.     hglobal = (HGLOBAL)GetClipboardData(CF_DIB);
  243.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  244.     palcolors = dib_pal_colors(pbmih);
  245.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  246.         palsize = palcolors * sizeof(RGBTRIPLE); 
  247.     else
  248.         palsize = palcolors * sizeof(RGBQUAD);
  249.  
  250.     hdc = GetDC(hwndimg);
  251.     hpalette = GetClipboardData(CF_PALETTE);
  252.     if (hpalette) {
  253.         SelectPalette(hdc,hpalette,NULL);
  254.         RealizePalette(hdc);
  255.     }
  256.     hbitmap = CreateDIBitmap(hdc, pbmih, CBM_INIT,
  257.         ((BYTE _huge *)pbmih) + pbmih->biSize + palsize,
  258.         (LPBITMAPINFO)pbmih, DIB_RGB_COLORS);
  259.     ReleaseDC(hwndimg, hdc);
  260.     GlobalUnlock(hglobal);
  261.     SetClipboardData(CF_BITMAP, hbitmap);
  262. }
  263.  
  264. /* make a DIB from a BITMAP in the clipboard */
  265. /* GetDIBits won't work for 4 plane or 4 bit/pixel bitmaps */
  266. /* clipboard must be open */
  267. HGLOBAL 
  268. make_dib(void)
  269. {
  270. LPBITMAPINFOHEADER pbmih;
  271. LPBITMAPINFO pbmi;
  272. BYTE FAR *lpBits;
  273. HBITMAP hbitmap;
  274. UINT palcolors;
  275. UINT palsize;
  276. UINT byte_width;
  277. DWORD bitmap_size;
  278. HGLOBAL hglobal;
  279. HDC hdc;
  280. HDC hdc_bit;
  281. BITMAP bm;
  282. PALETTEENTRY *pe;
  283. int i;
  284.     hbitmap = GetClipboardData(CF_BITMAP);
  285.     hdc = GetDC((HWND)NULL);
  286.     hdc_bit = CreateCompatibleDC(hdc);
  287.     ReleaseDC((HWND)NULL,hdc);
  288.     GetObject(hbitmap, sizeof(BITMAP), &bm);
  289.     if (bm.bmPlanes == 4) {
  290.         HBITMAP hbitmap_new, hbitmap_old;
  291.         HDC hdc_new;
  292.         /* convert format to 1 plane, 1 bit/pixel */ 
  293.         bm.bmPlanes = 1;
  294.         bm.bmBitsPixel = 1;
  295.         hdc_new = CreateCompatibleDC(hdc_bit);
  296.         hbitmap_new = CreateBitmap(bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL);
  297.         SelectBitmap(hdc_new, hbitmap_new);
  298.         hbitmap_old = SelectBitmap(hdc_bit, hbitmap);
  299.         BitBlt(hdc_new, 0, 0, bm.bmWidth, bm.bmHeight, hdc_bit, 0, 0, SRCCOPY);
  300.         SelectBitmap(hdc_bit, hbitmap_old);
  301.         DeleteDC(hdc_new);
  302.         hbitmap = hbitmap_new;
  303.     }
  304.      byte_width = (((bm.bmWidth * bm.bmBitsPixel + 31) & ~31) >> 3);
  305.     bitmap_size = (DWORD)bm.bmHeight *  byte_width;
  306.     palcolors = 1<<(bm.bmBitsPixel * bm.bmPlanes);
  307.     palsize = palcolors * sizeof(RGBQUAD);
  308.     hglobal = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + palsize + bitmap_size);
  309.     if (hglobal != (HGLOBAL)NULL) {
  310.         lpBits = GlobalLock(hglobal);
  311.         pbmi = (LPBITMAPINFO)lpBits;
  312.         pbmih = (LPBITMAPINFOHEADER)lpBits;
  313.         lpBits += sizeof(BITMAPINFOHEADER) + palsize;
  314.         pbmih->biSize = sizeof(BITMAPINFOHEADER);
  315.         pbmih->biWidth = bm.bmWidth;
  316.         pbmih->biHeight = bm.bmHeight;
  317.         pbmih->biPlanes = 1;
  318.         pbmih->biBitCount = bm.bmBitsPixel * bm.bmPlanes;
  319.         pbmih->biCompression = BI_RGB;
  320.         pbmih->biSizeImage = bitmap_size;
  321.         pbmih->biXPelsPerMeter = (int)(xdpi / 25.4 * 1000);
  322.         pbmih->biYPelsPerMeter = (int)(ydpi / 25.4 * 1000);
  323.         pbmih->biClrUsed = palcolors;
  324.         pbmih->biClrImportant = palcolors;
  325.         /* create colour table from system palette */
  326.         pe = malloc(palcolors * sizeof(PALETTEENTRY));
  327.         if (IsClipboardFormatAvailable(CF_PALETTE)) {
  328.         HPALETTE hpalette = GetClipboardData(CF_PALETTE);
  329.         i = GetObject(hpalette, sizeof(int), pe);
  330.         GetPaletteEntries(hpalette, 0, i, pe);
  331.         }
  332.         else
  333.             GetSystemPaletteEntries(hdc_bit, 0, palcolors, pe);
  334.         for (i=0; i<palcolors; i++) {
  335.         pbmi->bmiColors[i].rgbRed = pe[i].peRed;
  336.         pbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
  337.         pbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
  338.         pbmi->bmiColors[i].rgbReserved = 0;
  339.         }
  340.         free((void *)pe);
  341.         i = GetDIBits(hdc_bit, hbitmap, 0, (UINT)pbmih->biHeight,
  342.         lpBits, pbmi, DIB_RGB_COLORS);
  343.         GlobalUnlock(hglobal);
  344.         if (i == 0) {
  345.         GlobalFree(hglobal);
  346.         hglobal = NULL;
  347.         }
  348.     }
  349.     DeleteDC(hdc_bit);
  350.     if (hbitmap != GetClipboardData(CF_BITMAP))
  351.         DeleteBitmap(hbitmap);
  352.     return hglobal;
  353. }
  354.  
  355. /* Read DDB from the clipboard, convert to DIB and add to clipboard */
  356. void
  357. clip_add_dib(void)
  358. {
  359. HGLOBAL hglobal;
  360.     hglobal = make_dib();
  361.     if (hglobal != (HGLOBAL)NULL)
  362.             SetClipboardData(CF_DIB, hglobal);
  363. }
  364.  
  365. /* extract temp PS file from EPS dfile */
  366. /* point dfile at temp PS file */
  367. void extract_eps(void)
  368. {
  369. DWORD pos;
  370. DWORD len;
  371. FILE *f;
  372. UINT count;
  373. char *buffer;
  374. DWORD dtemp;
  375.     rewind(dfile);
  376.     fread(&dtemp, 4, 1, dfile);    /* ignore ID */
  377.     fread(&pos, 4, 1, dfile);    /* PS offset */
  378.     fread(&len, 4, 1, dfile);    /* PS length */
  379.     fread(&dtemp, 4, 1, dfile);    /* Metafile offset */
  380.     if (dtemp != 0L)
  381.         preview = IDS_EPSW;
  382.     else {
  383.         fread(&dtemp, 4, 1, dfile);    /* Metafile length */
  384.         fread(&dtemp, 4, 1, dfile);    /* TIFF offset */
  385.         if (dtemp != 0L)
  386.             preview = IDS_EPST;
  387.     }
  388.     fseek(dfile, pos, SEEK_SET);    /* seek to PS section */
  389.     /* remove old file */
  390.     if ((efname[0] != '\0') && !debug)
  391.         unlink(efname);
  392.     efname[0] = '\0';
  393.     /* get new scratch file */
  394.     if ( (f = gp_open_scratch_file(szScratch, efname, "wb")) == (FILE *)NULL) {
  395.         play_sound(SOUND_ERROR);
  396.         return;
  397.     }
  398.     
  399.     /* create buffer for PS file copy */
  400.     buffer = malloc(COPY_BUF_SIZE);
  401.     if (buffer == (char *)NULL) {
  402.         play_sound(SOUND_ERROR);
  403.         fclose(f);
  404.         return;
  405.     }
  406.  
  407.         while ( (count = (UINT)min(len,COPY_BUF_SIZE)) != 0 ) {
  408.         count = fread(buffer, 1, count, dfile);
  409.         fwrite(buffer, 1, count, f);
  410.         len -= count;
  411.     }
  412.     free(buffer);
  413.     fclose(f);
  414.     fclose(dfile);
  415.     dfile = fopen(efname, "rb");
  416. }
  417.  
  418. typedef struct {
  419.     DWORD    key;
  420.     HMETAFILE    hmf;
  421.     RECT    bbox;
  422.     WORD    inch;
  423.     DWORD    reserved;
  424.     WORD    checksum;
  425. } METAFILEHEADER;
  426.  
  427. /* extract EPS or TIFF or WMF file from DOS EPS file */
  428. void extract_doseps(WORD command)
  429. {
  430. DWORD pos;
  431. DWORD len;
  432. UINT count;
  433. char *buffer;
  434. FILE* epsfile;
  435. BOOL is_meta = TRUE;
  436. char outname[MAXSTR];
  437. FILE *outfile;
  438. UINT filter;
  439.     if (!preview || (preview == IDS_EPSI)) {
  440.         gserror(IDS_NOPREVIEW, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  441.         return;
  442.     }
  443.     epsfile = fopen(dfname,"rb");
  444.     fread(&pos, 4, 1, epsfile);        /* ignore ID */
  445.     fread(&pos, 4, 1, epsfile);        /* PS offset */
  446.     fread(&len, 4, 1, epsfile);        /* PS length */
  447.     if (command == IDM_EXTRACTPRE) {
  448.         fread(&pos, 4, 1, epsfile);        /* Metafile offset */
  449.         fread(&len, 4, 1, epsfile);        /* Metafile length */
  450.         if (pos == 0L) {
  451.             fread(&pos, 4, 1, epsfile);    /* TIFF offset */
  452.             fread(&len, 4, 1, epsfile);    /* TIFF length */
  453.             is_meta = FALSE;
  454.         }
  455.     }
  456.     if (pos == 0L) {
  457.         fclose(epsfile);
  458.         gserror(IDS_NOPREVIEW, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  459.         return;
  460.     }
  461.     fseek(epsfile, pos, SEEK_SET);    /* seek to section to extract */
  462.  
  463.     /* create postscript or preview file */
  464.     outname[0] = '\0';
  465.     if (command == IDM_EXTRACTPRE) {
  466.         if (is_meta)
  467.             filter = FILTER_WMF;
  468.         else
  469.             filter = FILTER_TIFF;
  470.     }
  471.     else
  472.         filter = FILTER_EPS;
  473.     if (!getfilename(outname, SAVE, filter, NULL, IDS_TOPICEDIT)) {
  474.         fclose(epsfile);
  475.         return;
  476.     }
  477.  
  478.     outfile = fopen(outname, "wb");
  479.     if (outfile == (FILE *)NULL) {
  480.         play_sound(SOUND_ERROR);
  481.         fclose(epsfile);
  482.         return;
  483.     }
  484.     
  485.     /* create buffer for file copy */
  486.     buffer = malloc(COPY_BUF_SIZE);
  487.     if (buffer == (char *)NULL) {
  488.         play_sound(SOUND_ERROR);
  489.         fclose(epsfile);
  490.         fclose(outfile);
  491.         return;
  492.     }
  493.  
  494.     if ((command == IDM_EXTRACTPRE) && is_meta) {
  495.         /* write placeable Windows Metafile header */
  496.         METAFILEHEADER mfh;
  497.         int i;
  498.         WORD *pw;
  499.         mfh.key = 0x9ac6cdd7L;
  500.         mfh.hmf = 0;
  501.         mfh.bbox.left = 0;
  502.         mfh.bbox.right = doc->boundingbox[URX] - doc->boundingbox[LLX];
  503.         mfh.bbox.top = 0;
  504.         mfh.bbox.bottom = doc->boundingbox[URY] - doc->boundingbox[LLY];
  505.         mfh.inch = 72;    /* PostScript points */
  506.         mfh.reserved = 0L;
  507.         mfh.checksum =  0;
  508.         pw = (WORD *)&mfh;
  509.         for (i=0; i<10; i++) {
  510.             mfh.checksum ^= *pw++;
  511.         }
  512.         fwrite(&mfh, sizeof(mfh), 1, outfile);
  513.     }
  514.  
  515.         while ( (count = (UINT)min(len,COPY_BUF_SIZE)) != 0 ) {
  516.         count = fread(buffer, 1, count, epsfile);
  517.         fwrite(buffer, 1, count, outfile);
  518.         len -= count;
  519.     }
  520.     free(buffer);
  521.     fclose(epsfile);
  522.     fclose(outfile);
  523. }
  524.  
  525. /* convert a clipboard bitmap to a metafile picture */
  526. HMETAFILE
  527. make_metafile(void)
  528. {
  529. HDC hdc;
  530. HMETAFILE hmf;
  531. HGLOBAL hglobal;
  532.     if (IsClipboardFormatAvailable(CF_DIB)) {
  533.         LPBITMAPINFOHEADER pbmih;
  534.         BYTE _huge *lpDibBits;
  535.         hglobal = GetClipboardData(CF_DIB);
  536.         pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  537.         lpDibBits = ((BYTE _huge *)pbmih) + pbmih->biSize;
  538.         if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  539.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBTRIPLE); 
  540.         else
  541.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBQUAD); 
  542.         /* now make a Metafile from it */
  543.         hdc = CreateMetaFile(NULL);
  544.         SetWindowOrg(hdc, 0, 0);
  545.         SetWindowExt(hdc, (int)pbmih->biWidth, (int)pbmih->biHeight);
  546.         StretchDIBits(hdc, 0, 0, (int)pbmih->biWidth, (int)pbmih->biHeight,
  547.             0, 0, (int)pbmih->biWidth, (int)pbmih->biHeight,
  548.             (void FAR *)lpDibBits, (LPBITMAPINFO)pbmih,
  549.             DIB_RGB_COLORS, SRCCOPY);
  550.         hmf = CloseMetaFile(hdc);
  551.         GlobalUnlock(hglobal);
  552.     }
  553.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  554.         HBITMAP hbitmap, hbitmap_old;
  555.         HDC hdc_bit;
  556.         BITMAP bm;
  557.         hbitmap = GetClipboardData(CF_BITMAP);
  558.         hdc = GetDC((HWND)NULL);
  559.         hdc_bit = CreateCompatibleDC(hdc);
  560.         ReleaseDC((HWND)NULL,hdc);
  561.         GetObject(hbitmap, sizeof(BITMAP), &bm);
  562.         hdc = CreateMetaFile(NULL);
  563.         SetWindowOrg(hdc, 0, 0);
  564.         SetWindowExt(hdc, bm.bmWidth, bm.bmHeight);
  565.         hbitmap_old = SelectBitmap(hdc_bit, hbitmap);
  566.         StretchBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight,
  567.             hdc_bit, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  568.         SelectBitmap(hdc_bit, hbitmap_old);
  569.         DeleteDC(hdc_bit);
  570.         hmf = CloseMetaFile(hdc);
  571.     }
  572.     else {
  573.         play_sound(SOUND_ERROR);
  574.         hmf = NULL;
  575.     }
  576.     return hmf;
  577. }
  578.  
  579. #ifdef NOT_USED
  580. /* not used */
  581. /* Read bitmap (CF_DIB or CF_BITMAP) from the clipboard */
  582. /* convert to Metafile Picture and add to clipboard */
  583. void
  584. clip_add_metafile(void)
  585. {
  586. LPMETAFILEPICT lpmfp;
  587. HGLOBAL hglobal;
  588. HMETAFILE hmf;
  589.     if ( (hmf = make_metafile()) == (HMETAFILE)NULL ) {
  590.         return;
  591.     }
  592.  
  593.     hglobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(METAFILEPICT)); 
  594.     lpmfp = GlobalLock(hglobal);
  595.     lpmfp->mm = MM_ANISOTROPIC;
  596.     if (bitmap_width)
  597.         lpmfp->xExt = (int)(bitmap_width / xdpi * 2540);
  598.     else 
  599.         lpmfp->xExt = 21000;    /* A4 */
  600.     if (bitmap_height)
  601.         lpmfp->yExt = (int)(bitmap_height / ydpi * 2540);
  602.     else
  603.         lpmfp->yExt = 29700;    /* A4 */
  604.     lpmfp->hMF = hmf;
  605.     GlobalUnlock(hglobal);
  606.     SetClipboardData(CF_METAFILEPICT, hglobal);
  607.     return;
  608. }
  609. #endif
  610.  
  611. struct eps_header_s {
  612.    char id[4];
  613.    DWORD ps_begin;
  614.    DWORD ps_length;
  615.    DWORD mf_begin;
  616.    DWORD mf_length;
  617.    DWORD tiff_begin;
  618.    DWORD tiff_length;
  619.    WORD  checksum;
  620. };
  621.  
  622. /* make a PC EPS file with a Windows Metafile Preview */
  623. /* from a PS file and a clipboard bitmap */
  624. void
  625. make_eps_metafile(void)
  626. {
  627. char epsname[MAXSTR];
  628. HMETAFILE hmf;
  629. HGLOBAL hglobal;
  630. char *buffer;
  631. UINT count;
  632. HFILE hfEPS;
  633. struct eps_header_s eps_header;
  634.  
  635.     if (!OpenClipboard(hwndimg)) {
  636.         play_sound(SOUND_ERROR);
  637.         return;
  638.     }
  639.  
  640.     if ( (hmf = make_metafile()) == (HMETAFILE)NULL ) {
  641.         play_sound(SOUND_ERROR);
  642.         CloseClipboard();
  643.         return;
  644.     }
  645.  
  646.     CloseClipboard();
  647.  
  648.     /* get memory handle to metafile */
  649.     hglobal = GetMetaFileBits(hmf);
  650.  
  651.     /* create buffer for PS file copy */
  652.     buffer = malloc(COPY_BUF_SIZE);
  653.     if (buffer == (char *)NULL) {
  654.         GlobalFree(hglobal);
  655.         gserror(IDS_BADEPS, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  656.         return;
  657.     }
  658.  
  659.     /* create EPS file */
  660.     epsname[0] = '\0';
  661.     if (!getfilename(epsname, SAVE, FILTER_EPS, NULL, IDS_TOPICEDIT)) {
  662.         GlobalFree(hglobal);
  663.         return;
  664.     }
  665.     hfEPS = _lcreat(epsname, 0);
  666.  
  667.     /* write DOS EPS binary header */
  668.     eps_header.id[0] = 0xc5;    /* "EPSF" with bit 7 set */
  669.     eps_header.id[1] = 0xd0;
  670.     eps_header.id[2] = 0xd3;
  671.     eps_header.id[3] = 0xc6;
  672.     eps_header.ps_begin = sizeof(eps_header);
  673.     fseek(dfile, 0, SEEK_END);
  674.     eps_header.ps_length = ftell(dfile);
  675.     eps_header.mf_begin = eps_header.ps_begin + eps_header.ps_length;
  676.     eps_header.mf_length = GlobalSize(hglobal);
  677.     eps_header.tiff_begin = 0;
  678.     eps_header.tiff_length = 0;
  679.     eps_header.checksum = -1;
  680.     _lwrite(hfEPS, (void _huge *)&eps_header, sizeof(eps_header));
  681.  
  682.     /* copy PS file */
  683.     rewind(dfile);
  684.     do {
  685.         count = fread(buffer, 1, COPY_BUF_SIZE, dfile);
  686.         _lwrite(hfEPS, buffer, count);
  687.     } while (count != 0);
  688.     free(buffer);
  689.  
  690.     /* copy metafile */
  691.     hwrite(hfEPS, GlobalLock(hglobal), eps_header.mf_length);
  692.     GlobalUnlock(hglobal);
  693.     GlobalFree(hglobal);
  694.  
  695.     _lclose(hfEPS);
  696. }
  697.  
  698.  
  699. char hex[16] = "0123456789ABCDEF";
  700. unsigned char isblack[256];
  701.  
  702. void
  703. scan_colors(LPBITMAPINFOHEADER pbmih)
  704. {
  705.     RGBQUAD FAR *prgbquad;
  706.     RGBTRIPLE FAR *prgbtriple;
  707.     unsigned char rr;
  708.     unsigned char gg;
  709.     unsigned char bb;
  710.     int isOS2 = FALSE;
  711.     int clrtablesize;
  712.     int i;
  713.  
  714.     prgbquad   = (RGBQUAD FAR *)(((BYTE _huge *)pbmih) + pbmih->biSize);
  715.     prgbtriple = (RGBTRIPLE FAR *)prgbquad;
  716.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  717.         isOS2 = TRUE;
  718.     /* read in the color table */
  719.     clrtablesize = dib_pal_colors(pbmih);
  720.     for (i = 0; i < clrtablesize; i++) {
  721.         if (isOS2) {
  722.             bb = prgbtriple[i].rgbtBlue;
  723.             gg = prgbtriple[i].rgbtGreen;
  724.             rr = prgbtriple[i].rgbtRed;
  725.         }
  726.         else {
  727.             bb = prgbquad[i].rgbBlue;
  728.             gg = prgbquad[i].rgbGreen;
  729.             rr = prgbquad[i].rgbRed;
  730.         }
  731.         isblack[i] = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
  732.     }
  733. }
  734.  
  735. BYTE _huge *
  736. get_dib_bits(LPBITMAPINFOHEADER pbmih)
  737. {
  738. BYTE _huge *lpDibBits;
  739.     lpDibBits = (((BYTE _huge *)pbmih) + pbmih->biSize);
  740.     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
  741.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBTRIPLE); 
  742.     else
  743.         lpDibBits += dib_pal_colors(pbmih) * sizeof(RGBQUAD); 
  744.     return lpDibBits;
  745. }
  746.  
  747. void
  748. get_dib_line(BYTE _huge *line, char *preview, int width, int bitcount)
  749. {
  750. int bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */
  751. unsigned char omask;
  752. int oroll;
  753. unsigned char c = 0;
  754. int j;
  755.     memset(preview,0xff,bwidth);
  756.     omask = 0x80;
  757.     oroll = 7;
  758.     if (bitcount == 1) {
  759.         if (isblack[0])
  760.         for (j = 0; j < bwidth ; j++)
  761.             preview[j] = line[j];
  762.         else
  763.         for (j = 0; j < bwidth ; j++)
  764.             preview[j] = ~line[j];
  765.         preview[bwidth-1] |= width & 7 ? (1<<(8-(width&7)))-1 : 0;    /* mask for edge of bitmap */
  766.     }
  767.     else {
  768.         for (j = 0; j < width; j++) {
  769.         switch (bitcount) {
  770.             case 4:
  771.                 c = line[j>>1];
  772.                 if (!(j&1))
  773.                     c >>= 4;
  774.                 c = isblack[ c & 0x0f ];
  775.                 break;
  776.             case 8:
  777.                 c = isblack[ (int)(line[j]) ];
  778.                 break;
  779.             case 24:
  780.                 c = (line[j*3] < 0xff) || 
  781.                     (line[j*3+1] < 0xff) || 
  782.                     (line[j*3+2] < 0xff);
  783.                 break;
  784.         }
  785.         if (c) 
  786.             preview[j/8] &= ~omask;
  787.         else
  788.             preview[j/8] |= omask;
  789.         oroll--;
  790.         omask >>= 1;
  791.         if (oroll < 0) {
  792.             omask = 0x80;
  793.             oroll = 7;
  794.         }
  795.         }
  796.     }
  797. }
  798.  
  799. #define TIFF_BYTE 1
  800. #define TIFF_ASCII 2
  801. #define TIFF_SHORT 3
  802. #define TIFF_LONG 4
  803. #define TIFF_RATIONAL 5
  804.  
  805. struct rational_s {
  806.     DWORD numerator;
  807.     DWORD denominator;
  808. };
  809.  
  810. struct ifd_entry_s {
  811.     WORD tag;
  812.     WORD type;
  813.     DWORD length;
  814.     DWORD value;
  815. };
  816.  
  817. struct tiff_head_s {
  818.     WORD order;
  819.     WORD version;
  820.     DWORD ifd_offset;
  821.     WORD ifd_length;
  822. };
  823.  
  824. /* write tiff file from DIB bitmap */
  825. /* hglobal is handle to DIB in memory */
  826. void
  827. write_tiff(FILE *f, HGLOBAL hglobal)
  828. {
  829. char *now;
  830. DWORD *strip;
  831. #define IFD_ENTRY_COUNT 12
  832. struct tiff_head_s tiff_head;
  833. WORD ifd_length;
  834. DWORD ifd_next;
  835. struct ifd_entry_s ifd_entry[IFD_ENTRY_COUNT];
  836. struct ifd_entry_s *pifd_entry;
  837. struct rational_s rational;
  838. DWORD tiff_end, end;
  839. time_t t;
  840. int i;
  841. char *preview;
  842. LPBITMAPINFOHEADER pbmih;
  843. BYTE _huge *lpDibBits;
  844. BYTE _huge *line;
  845. int width;
  846. int height;
  847. int bitcount;
  848. int bwidth;
  849. BOOL soft_extra = FALSE;
  850. BOOL date_extra = FALSE;
  851.     
  852.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  853.     lpDibBits = get_dib_bits(pbmih);
  854.  
  855.     width = (int)pbmih->biWidth;
  856.     height = (int)pbmih->biHeight;
  857.     bitcount = pbmih->biBitCount;
  858.     /* byte width with 1 bit/pixel, rounded up even word */
  859.     bwidth = ((width + 15) & ~15) >> 3;
  860.     height = (int)pbmih->biHeight;
  861.  
  862.     tiff_end = sizeof(tiff_head);
  863.     tiff_head.order = 0x4949;
  864.     tiff_head.version = 42;
  865.     tiff_head.ifd_offset = tiff_end;
  866.  
  867.     tiff_end += sizeof(ifd_length);
  868.     ifd_length = IFD_ENTRY_COUNT;
  869.  
  870.     tiff_end += sizeof(ifd_entry) + sizeof(ifd_next);
  871.     ifd_next = 0;
  872.     pifd_entry = &ifd_entry[0];
  873.     pifd_entry->tag = 0xfe;        /* NewSubFileType */
  874.     pifd_entry->type = TIFF_LONG;
  875.     pifd_entry->length = 1;
  876.     pifd_entry->value = 0;
  877.  
  878.     pifd_entry = &ifd_entry[1];
  879.     pifd_entry->tag = 0x100;    /* ImageWidth */
  880.     pifd_entry->type = TIFF_LONG;
  881.     pifd_entry->length = 1;
  882.     pifd_entry->value = pbmih->biWidth;
  883.  
  884.     pifd_entry = &ifd_entry[2];
  885.     pifd_entry->tag = 0x101;    /* ImageLength */
  886.     pifd_entry->type = TIFF_LONG;
  887.     pifd_entry->length = 1;
  888.     pifd_entry->value = height;
  889.  
  890.     pifd_entry = &ifd_entry[3];
  891.     pifd_entry->tag = 0x103;    /* Compression */
  892.     pifd_entry->type = TIFF_SHORT;
  893.     pifd_entry->length = 1;
  894.     pifd_entry->value = 1;        /* no compression */
  895.  
  896.     pifd_entry = &ifd_entry[4];
  897.     pifd_entry->tag = 0x106;    /* PhotometricInterpretation */
  898.     pifd_entry->type = TIFF_SHORT;
  899.     pifd_entry->length = 1;
  900.     pifd_entry->value = 1;        /* black is zero */
  901.  
  902.     pifd_entry = &ifd_entry[5];
  903.     pifd_entry->tag = 0x111;    /* StripOffsets */
  904.     pifd_entry->type = TIFF_LONG;
  905.     pifd_entry->length = height;
  906.     pifd_entry->value = tiff_end;
  907.     tiff_end += (pifd_entry->length * sizeof(DWORD));
  908.  
  909.     pifd_entry = &ifd_entry[6];
  910.     pifd_entry->tag = 0x116;    /* RowsPerStrip */
  911.     pifd_entry->type = TIFF_LONG;
  912.     pifd_entry->length = 1;
  913.     pifd_entry->value = 1;
  914.  
  915.     pifd_entry = &ifd_entry[7];
  916.     pifd_entry->tag = 0x117;    /* StripByteCounts */
  917.     pifd_entry->type = TIFF_LONG;
  918.     pifd_entry->length = height;
  919.     pifd_entry->value = tiff_end;
  920.     tiff_end += (pifd_entry->length * sizeof(DWORD));
  921.  
  922.     pifd_entry = &ifd_entry[8];
  923.     pifd_entry->tag = 0x11a;    /* XResolution */
  924.     pifd_entry->type = TIFF_RATIONAL;
  925.     pifd_entry->length = 1;
  926.     pifd_entry->value = tiff_end;
  927.     tiff_end += sizeof(struct rational_s);
  928.  
  929.     pifd_entry = &ifd_entry[9];
  930.     pifd_entry->tag = 0x11b;    /* YResolution */
  931.     pifd_entry->type = TIFF_RATIONAL;
  932.     pifd_entry->length = 1;
  933.     pifd_entry->value = tiff_end;
  934.     tiff_end += sizeof(struct rational_s);
  935.  
  936.     pifd_entry = &ifd_entry[10];
  937.     pifd_entry->tag = 0x131;    /* Software */
  938.     pifd_entry->type = TIFF_ASCII;
  939.     pifd_entry->length = strlen(szAppName) + 1;
  940.     pifd_entry->value = tiff_end;
  941.     tiff_end += pifd_entry->length;
  942.     if (tiff_end & 1) { /* pad to word boundary */
  943.         soft_extra = TRUE;
  944.         tiff_end++;
  945.     }
  946.  
  947.     pifd_entry = &ifd_entry[11];
  948.     pifd_entry->tag = 0x132;    /* DateTime */
  949.     pifd_entry->type = TIFF_ASCII;
  950.     t = time(NULL);
  951.     now = ctime(&t);
  952.     now[strlen(now)-1] = '\0';    /* remove trailing \n */
  953.     pifd_entry->length = strlen(now)+1;
  954.     pifd_entry->value = tiff_end;
  955.     tiff_end += pifd_entry->length;
  956.     if (tiff_end & 1) { /* pad to word boundary */
  957.         date_extra = TRUE;
  958.         tiff_end++;
  959.     }
  960.  
  961.     fwrite(&tiff_head, sizeof(tiff_head), 1, f);
  962.     fwrite(&ifd_length, sizeof(ifd_length), 1, f);
  963.     fwrite(&ifd_entry, sizeof(ifd_entry), 1, f);
  964.     fwrite(&ifd_next, sizeof(ifd_next), 1, f);
  965.     strip = (DWORD *)malloc(height * sizeof(DWORD));
  966.     end = tiff_end;
  967.     for (i=0; i<height; i++) {
  968.         strip[i] = end;        /* strip offsets */
  969.         end += bwidth;
  970.     }
  971.     fwrite(strip, 1, height * sizeof(DWORD), f);
  972.     for (i=0; i<height; i++)
  973.         strip[i] = bwidth;    /* strip byte counts */
  974.     fwrite(strip, 1, height * sizeof(DWORD), f);
  975.     free((void *)strip);
  976.     rational.numerator = (int)xdpi;
  977.     rational.denominator = 1;
  978.     fwrite(&rational, sizeof(rational), 1, f);
  979.     rational.numerator = (int)ydpi;
  980.     rational.denominator = 1;
  981.     fwrite(&rational, sizeof(rational), 1, f);
  982.     fwrite(szAppName, 1, strlen(szAppName)+1, f);
  983.     if (soft_extra)
  984.         fputc('\0',f);
  985.     fwrite(now, 1, strlen(now)+1, f);
  986.     if (date_extra)
  987.         fputc('\0',f);
  988.  
  989.     scan_colors(pbmih);
  990.  
  991.     preview = (char *) malloc(bwidth);
  992.     memset(preview,0xff,bwidth);
  993.  
  994.     line = lpDibBits + (dib_bytewidth(pbmih) * pbmih->biHeight);
  995.     /* process each line of bitmap */
  996.     for (i = 0; i < pbmih->biHeight; i++) {
  997.         line -= dib_bytewidth(pbmih);
  998.         get_dib_line(line, preview, width, bitcount);
  999.         fwrite(preview, 1, bwidth, f);
  1000.     }
  1001.     free(preview);
  1002.     GlobalUnlock(hglobal);
  1003. }
  1004.  
  1005. /* make a PC EPS file with a TIFF Preview */
  1006. /* from a PS file and a clipboard bitmap */
  1007. void
  1008. make_eps_tiff(void)
  1009. {
  1010. char epsname[MAXSTR];
  1011. HGLOBAL hglobal;
  1012. char *buffer;
  1013. UINT count;
  1014. FILE *epsfile;
  1015. FILE *tiff_file;
  1016. char tiffname[MAXSTR];
  1017. BOOL made_dib = FALSE;
  1018. struct eps_header_s eps_header;
  1019.  
  1020.     if (!OpenClipboard(hwndimg)) {
  1021.         play_sound(SOUND_ERROR);
  1022.         return;
  1023.     }
  1024.     if (IsClipboardFormatAvailable(CF_DIB))
  1025.         hglobal = GetClipboardData(CF_DIB);
  1026.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  1027.         /* untested */
  1028.         hglobal = make_dib(); /* convert to DIB format */
  1029.         if (hglobal == (HGLOBAL)NULL) {
  1030.             play_sound(SOUND_ERROR);
  1031.             CloseClipboard();
  1032.             return;
  1033.         }
  1034.         made_dib = TRUE;
  1035.     }
  1036.     else {
  1037.         play_sound(SOUND_ERROR);
  1038.         CloseClipboard();
  1039.         return;
  1040.     }
  1041.     
  1042.     if ( (tiff_file = gp_open_scratch_file(szScratch, tiffname, "wb")) == (FILE *)NULL) {
  1043.         play_sound(SOUND_ERROR);
  1044.         if (made_dib)
  1045.             GlobalFree(hglobal);
  1046.         CloseClipboard();
  1047.         return;
  1048.     }
  1049.     write_tiff(tiff_file, hglobal);
  1050.     fclose(tiff_file);
  1051.     CloseClipboard();
  1052.     if (made_dib)
  1053.         GlobalFree(hglobal);
  1054.  
  1055.     /* create EPS file */
  1056.     epsname[0] = '\0';
  1057.     if (!getfilename(epsname, SAVE, FILTER_EPS, NULL, IDS_TOPICEDIT)) {
  1058.         unlink(tiffname);
  1059.         return;
  1060.     }
  1061.     epsfile = fopen(epsname,"wb");
  1062.  
  1063.     /* write DOS EPS binary header */
  1064.     eps_header.id[0] = 0xc5;
  1065.     eps_header.id[1] = 0xd0;
  1066.     eps_header.id[2] = 0xd3;
  1067.     eps_header.id[3] = 0xc6;
  1068.     eps_header.ps_begin = sizeof(eps_header);
  1069.     fseek(dfile, 0, SEEK_END);
  1070.     eps_header.ps_length = ftell(dfile);
  1071.     eps_header.mf_begin = 0;
  1072.     eps_header.mf_length = 0;
  1073.     eps_header.tiff_begin = eps_header.ps_begin + eps_header.ps_length;
  1074.     tiff_file = fopen(tiffname,"rb");
  1075.     fseek(tiff_file, 0, SEEK_END);
  1076.     eps_header.tiff_length = ftell(tiff_file);;
  1077.     eps_header.checksum = -1;
  1078.  
  1079.     fwrite(&eps_header, sizeof(eps_header), 1, epsfile);
  1080.     rewind(dfile);
  1081.     pscopy(dfile, epsfile, doc->beginheader, doc->endtrailer);
  1082.     
  1083.     /* copy tiff file */
  1084.     rewind(tiff_file);
  1085.     buffer = malloc(COPY_BUF_SIZE);
  1086.     if (buffer == (char *)NULL) {
  1087.         play_sound(SOUND_ERROR);
  1088.         fclose(epsfile);
  1089.         unlink(epsname);
  1090.         fclose(tiff_file);
  1091.         unlink(tiffname);
  1092.         return;
  1093.     }
  1094.         while ( (count = fread(buffer, 1, COPY_BUF_SIZE, tiff_file)) != 0 )
  1095.         fwrite(buffer, 1, count, epsfile);
  1096.     free(buffer);
  1097.     fclose(tiff_file);
  1098.     unlink(tiffname);
  1099.     fclose(epsfile);
  1100. }
  1101.  
  1102.  
  1103. /* write interchange preview to file f */
  1104. /* hglobal is handle to DIB in memory */
  1105. void
  1106. write_interchange(FILE *f, HGLOBAL hglobal)
  1107. {
  1108.     int i, j;
  1109.     char *preview;
  1110.     LPBITMAPINFOHEADER pbmih;
  1111.     BYTE _huge *lpDibBits;
  1112.     BYTE _huge *line;
  1113.     int width;
  1114.     int height;
  1115.     int bitcount;
  1116.     int bwidth;
  1117.     int lines_per_scan;
  1118.     
  1119.     pbmih = (LPBITMAPINFOHEADER)GlobalLock(hglobal);
  1120.     lpDibBits = get_dib_bits(pbmih);
  1121.  
  1122.     width = (int)pbmih->biWidth;
  1123.     height = (int)pbmih->biHeight;
  1124.     bitcount = pbmih->biBitCount;
  1125.     bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */
  1126.  
  1127.     scan_colors(pbmih);
  1128.  
  1129.     preview = (char *) malloc(bwidth);
  1130.  
  1131.     lines_per_scan = ((bwidth-1) / 32) + 1;
  1132.     fprintf(f,"%%%%BeginPreview: %u %u 1 %u\r\n",width, height, 
  1133.         height*lines_per_scan);
  1134.  
  1135.     line = lpDibBits + (dib_bytewidth(pbmih) * pbmih->biHeight);
  1136.     /* process each line of bitmap */
  1137.     for (i = 0; i < pbmih->biHeight; i++) {
  1138.         line -= dib_bytewidth(pbmih);
  1139.         get_dib_line(line, preview, width, bitcount);
  1140.         fputs("% ",f);
  1141.         for (j=0; j<bwidth; j++) {
  1142.             if (j && ((j & 31) == 0))
  1143.                 fputs("\r\n% ",f);
  1144.             fputc(hex[15-((preview[j]>>4)&15)],f);
  1145.             fputc(hex[15-((preview[j])&15)],f);
  1146.         }
  1147.         fputs("\r\n",f);
  1148.     }
  1149.  
  1150.     fputs("%%EndPreview\r\n",f);
  1151.     free(preview);
  1152.     GlobalUnlock(hglobal);
  1153. }
  1154.  
  1155. /* make an EPSI file with an Interchange Preview */
  1156. /* from a PS file and a clipboard bitmap */
  1157. void
  1158. make_eps_interchange(void)
  1159. {
  1160. HGLOBAL hglobal;
  1161. char epiname[MAXSTR];
  1162. FILE *epifile;
  1163. BOOL made_dib = FALSE;
  1164.     if (!OpenClipboard(hwndimg)) {
  1165.         play_sound(SOUND_ERROR);
  1166.         return;
  1167.     }
  1168.     if (IsClipboardFormatAvailable(CF_DIB))
  1169.         hglobal = GetClipboardData(CF_DIB);
  1170.     else if (IsClipboardFormatAvailable(CF_BITMAP)) {
  1171.         /* untested */
  1172.         hglobal = make_dib(); /* convert to DIB format */
  1173.         if (hglobal == (HGLOBAL)NULL) {
  1174.             play_sound(SOUND_ERROR);
  1175.             CloseClipboard();
  1176.             return;
  1177.         }
  1178.         made_dib = TRUE;
  1179.     }
  1180.     else {
  1181.         play_sound(SOUND_ERROR);
  1182.         CloseClipboard();
  1183.         return;
  1184.     }
  1185.  
  1186.     /* create EPI file */
  1187.     epiname[0] = '\0';
  1188.     if (!getfilename(epiname, SAVE, FILTER_EPI, NULL, IDS_TOPICEDIT)) {
  1189.         play_sound(SOUND_ERROR);
  1190.         CloseClipboard();
  1191.         return;
  1192.     }
  1193.     
  1194.     if ((epifile = fopen(epiname,"wb")) == (FILE *)NULL) {
  1195.         play_sound(SOUND_ERROR);
  1196.         if (made_dib)
  1197.             GlobalFree(hglobal);
  1198.         CloseClipboard();
  1199.         return;
  1200.     }
  1201.  
  1202.     rewind(dfile);
  1203.     pscopy(dfile, epifile, doc->beginheader, doc->endheader);
  1204.     write_interchange(epifile,hglobal);
  1205.     pscopy(dfile, epifile, doc->endheader, doc->endtrailer);
  1206.     fclose(epifile);
  1207.     if (made_dib)
  1208.         GlobalFree(hglobal);
  1209.     CloseClipboard();
  1210. }
  1211.  
  1212. /* write prolog which produces warnings when operators that should */
  1213. /* not be included in EPS file are executed */
  1214. void
  1215. epsf_warnprolog(FILE *f)
  1216. {
  1217. HGLOBAL hglobal;
  1218. LPSTR prolog;
  1219.     hglobal = LoadResource(phInstance, FindResource(phInstance, "gsview_epswarn", RT_RCDATA));
  1220.     if ( (prolog = (LPSTR)LockResource(hglobal)) != (LPSTR)NULL) {
  1221.         while (*prolog)
  1222.             fputc(*prolog++, f);
  1223.         FreeResource(hglobal);
  1224.     }
  1225. }
  1226.  
  1227. int bbox[4];
  1228. BOOL bbflag;
  1229.  
  1230. BOOL CALLBACK _export
  1231. BoundingBoxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1232. {
  1233. static int bboxindex;
  1234. int x, y;
  1235. char buf[MAXSTR];
  1236.     switch(message) {
  1237.     case WM_INITDIALOG:
  1238.         bboxindex = 0;
  1239.         LoadString(phInstance, IDS_BBPROMPT, buf, sizeof(buf));
  1240.         SetDlgItemText(hDlg, BB_PROMPT, buf);
  1241.         return TRUE;
  1242.     case WM_COMMAND:
  1243.         switch(LOWORD(wParam)) {
  1244.         case BB_CLICK:
  1245.             if (!get_cursorpos(&x, &y)) {
  1246.             DestroyWindow(hDlg);
  1247.             hDlgModeless = 0;
  1248.             }
  1249.             switch(bboxindex) {
  1250.             case LLX:
  1251.             case URX:
  1252.                 bbox[bboxindex] = x;
  1253.                 break;
  1254.             case URY:
  1255.                 bbflag = TRUE;
  1256.             case LLY:
  1257.                 bbox[bboxindex] = y;
  1258.                 break;
  1259.             }
  1260.             bboxindex++;
  1261.             if (bboxindex <= URY) {
  1262.                     LoadString(phInstance, IDS_BBPROMPT+bboxindex, buf, sizeof(buf));
  1263.                     SetDlgItemText(hDlg, BB_PROMPT, buf);
  1264.             return FALSE;
  1265.             }
  1266.         case WM_CLOSE:
  1267.         case IDCANCEL:
  1268.             DestroyWindow(hDlg);
  1269.             hDlgModeless = 0;
  1270.             return TRUE;
  1271.         }
  1272.     }
  1273.     return FALSE;
  1274. }
  1275.  
  1276. BOOL
  1277. get_bbox(void)
  1278. {
  1279. DLGPROC lpfnBoundingBoxProc;
  1280.  
  1281.     bbflag = FALSE;
  1282.     bbox[LLX] = bbox[LLY] = bbox[URX] = bbox[URY] = 0;
  1283.     if (!page_ready) {
  1284.         gserror(IDS_EPSNOBBOX, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1285.         return FALSE;
  1286.     }
  1287.     lpfnBoundingBoxProc = (DLGPROC)MakeProcInstance((FARPROC)BoundingBoxDlgProc, phInstance);
  1288.     hDlgModeless = CreateDialogParam(phInstance, "BoundingBoxDlgBox", hwndimg, lpfnBoundingBoxProc, (LPARAM)NULL);
  1289.     while (hDlgModeless) {
  1290.         do_message();    /* wait for bounding box to be obtained */
  1291.     }
  1292.     FreeProcInstance((FARPROC)lpfnBoundingBoxProc);
  1293.     return bbflag;
  1294. }
  1295.  
  1296.  
  1297. /* At present only allows bounding box to be specified */
  1298. void
  1299. ps_to_eps(void)
  1300. {
  1301. char output[MAXSTR];
  1302. FILE *f;
  1303. char *buffer;
  1304. UINT count;
  1305. FILE *infile;
  1306. time_t t;
  1307. char *now;
  1308. char text[PSLINELENGTH];
  1309. char *comment;
  1310. long here;
  1311.  
  1312. /* should replace following Message Box with something more appropriate */
  1313.     if (MessageBox(hwndimg, "Have you read help `PS to EPS` ?",szAppName, MB_YESNO | MB_ICONQUESTION)
  1314.         != IDYES) {
  1315.         LoadString(phInstance, IDS_TOPICPSTOEPS, szHelpTopic, sizeof(szHelpTopic));
  1316.         SendMessage(hwndimg, help_message, 0, 0L);
  1317.         return;
  1318.     }
  1319.  
  1320.     if (!hwndimgchild || !IsWindow(hwndimgchild)) {
  1321.         gserror(IDS_EPSNOBBOX, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1322.         return;
  1323.     }
  1324.  
  1325.     if ((doc != (struct document *)NULL) && (doc->numpages > 1)) {
  1326.         gserror(IDS_EPSONEPAGE, NULL, MB_ICONEXCLAMATION, SOUND_ERROR);
  1327.         return;
  1328.     }
  1329.     if (doc == (struct document *)NULL) {
  1330.         char mess[MAXSTR];
  1331.         LoadString(phInstance, IDS_EPSQPAGES, mess, sizeof(mess));
  1332.         if (MessageBox(hwndimg, mess, szAppName, MB_YESNO | MB_ICONQUESTION) != IDYES)
  1333.         return;
  1334.     }
  1335.  
  1336.     if (!get_bbox()) {
  1337.         play_sound(SOUND_ERROR);
  1338.         return;
  1339.     }
  1340.  
  1341.     output[0] = '\0';
  1342.     if (!getfilename(output, SAVE, FILTER_EPS, NULL, IDS_TOPICPSTOEPS))
  1343.         return;
  1344.  
  1345.     if ((f = fopen(output, "wb")) == (FILE *)NULL) {
  1346.         play_sound(SOUND_ERROR);
  1347.         return;
  1348.     }
  1349.  
  1350.     if (doc == (struct document *)NULL) {
  1351.         info_wait(TRUE);
  1352.         fputs("%!PS-Adobe-3.0 EPSF-3.0\r\n",f);
  1353.         /* if this is not a single page document then gsview has just lied */
  1354.         fprintf(f, "%%%%BoundingBox: %u %u %u %u\r\n",
  1355.         bbox[LLX],bbox[LLY],bbox[URX],bbox[URY]);
  1356.         fprintf(f,"%%%%Title: %s\r\n",dfname);
  1357.         fprintf(f,"%%%%Creator: %s from %s\r\n",szAppName,dfname);
  1358.         t = time(NULL);
  1359.         now = ctime(&t);
  1360.         now[strlen(now)-1] = '\0';    /* remove trailing \n */
  1361.         fprintf(f,"%%%%CreationDate: %s\r\n",now);
  1362.         fputs("%%Pages: 1\r\n",f);
  1363.         fputs("%%EndComments\r\n",f);
  1364.  
  1365.         fputs("%%Page: 1 1\r\n",f);
  1366.         fprintf(f,"%%BeginDocument: %s\r\n",dfname);
  1367.  
  1368.         /* create buffer for PS file copy */
  1369.         buffer = malloc(COPY_BUF_SIZE);
  1370.         if (buffer == (char *)NULL) {
  1371.             play_sound(SOUND_ERROR);
  1372.             fclose(f);
  1373.         unlink(output);
  1374.             return;
  1375.         }
  1376.  
  1377.         infile = fopen(dfname, "rb");
  1378.         if (infile == (FILE *)NULL) {
  1379.             play_sound(SOUND_ERROR);
  1380.             fclose(f);
  1381.         unlink(output);
  1382.             return;
  1383.         }
  1384.  
  1385.             while ( (count = fread(buffer, 1, COPY_BUF_SIZE, infile)) != 0 ) {
  1386.             fwrite(buffer, 1, count, f);
  1387.         }
  1388.         free(buffer);
  1389.         fclose(infile);
  1390.  
  1391.         fputs("%%EndDocument\r\n",f);
  1392.         fputs("%%Trailer\r\n",f);
  1393.         fclose(f);
  1394.         info_wait(FALSE);
  1395.     }
  1396.     else {
  1397.         /* document already has DSC comments */
  1398.         info_wait(TRUE);
  1399.         rewind(dfile);
  1400.         if (is_ctrld)
  1401.             fgetc(dfile);
  1402.         fgets(text, PSLINELENGTH, dfile);
  1403.         if (doc->epsf)
  1404.             fputs(text,f);
  1405.         else
  1406.             fputs("%!PS-Adobe-3.0 EPSF-3.0\r\n",f);
  1407.         if ((doc->boundingbox[LLX] != 0) || (doc->boundingbox[LLY] != 0) || 
  1408.             (doc->boundingbox[URX] != 0) || (doc->boundingbox[URY] != 0)) {
  1409.             if ( (comment = pscopyuntil(dfile, f, -1,
  1410.                doc->endheader, "%%BoundingBox:")) != (char *)NULL ) {
  1411.             free(comment);
  1412.             }
  1413.         }
  1414.         fprintf(f, "%%%%BoundingBox: %u %u %u %u\r\n",
  1415.         bbox[LLX],bbox[LLY],bbox[URX],bbox[URY]);
  1416.         here = ftell(dfile);
  1417.         pscopy(dfile, f, here, doc->endtrailer);
  1418.         fclose(f);
  1419.         info_wait(FALSE);
  1420.     }
  1421. }
  1422.